﻿using System;
using System.Collections.Generic;
using GeoAPI.Geometries;
using HYCodeBase.Geometry;
using NetTopologySuite.Geometries;
using NetTopologySuite.IO;

namespace HYCodeBase.TopologySuite
{
	internal class NtsGeometryGeter
	{
		private NtsGeometryGeter()
		{
		}

		internal static NtsGeometryGeter GetNtsGeometryGeter()
		{
			if (NtsGeometryGeter.m_signalTag == null)
			{
				NtsGeometryGeter.m_signalTag = new NtsGeometryGeter();
			}
			return NtsGeometryGeter.m_signalTag;
		}

		private bool TryCreatLineString(string inputWKTString, out LineString creatResult)
		{
			creatResult = null;
			bool result;
			try
			{
				WKTReader wktreader = new WKTReader(this.m_useGeometryFactory);
				creatResult = (wktreader.Read(inputWKTString) as LineString);
				result = (null == creatResult);
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		internal List<LineSegment> GetLstLineSegementFromLineString(LineString inputLineString)
		{
			List<LineSegment> list = new List<LineSegment>();
			for (int i = 1; i < inputLineString.Coordinates.Length; i++)
			{
				list.Add(new LineSegment(inputLineString.Coordinates[i - 1], inputLineString.Coordinates[i]));
			}
			return list;
		}

		internal IGeometry CreatTotalGeometry(List<IGeometry> input)
		{
			return this.m_useGeometryFactory.BuildGeometry(input);
		}

		internal bool TryMakeLineString(HYMulPointXYZ inputPoints, out LineString creatResult, bool ifAddEndPointForRing = false)
		{
			creatResult = null;
			if (inputPoints == null || (ifAddEndPointForRing && inputPoints.Size < 3))
			{
				return false;
			}
			List<Coordinate> list = new List<Coordinate>();
			foreach (HYPointXYZ hypointXYZ in inputPoints)
			{
				if (hypointXYZ == null)
				{
					return false;
				}
				list.Add(this.CreatOneCoordinate(hypointXYZ.X, hypointXYZ.Y));
			}
			if (ifAddEndPointForRing && !list[0].Equals2D(list[list.Count - 1]))
			{
				list.Add(list[0]);
			}
			return this.TryCreatLine(list, out creatResult);
		}

		internal bool TryMakePolygon(HYMulPointXYZ inputShellPoints, out Polygon creatResult, bool ifAddEndPointForReing = false, List<HYMulPointXYZ> lstlstInputHolePoints = null)
		{
			creatResult = null;
			LineString lineString = null;
			List<LinearRing> list = null;
			if (!this.TryMakeLineString(inputShellPoints, out lineString, ifAddEndPointForReing) || !(lineString is LinearRing))
			{
				return false;
			}
			if (lstlstInputHolePoints != null)
			{
				list = new List<LinearRing>();
				LineString lineString2 = null;
				foreach (HYMulPointXYZ inputPoints in lstlstInputHolePoints)
				{
					if (!this.TryMakeLineString(inputPoints, out lineString2, ifAddEndPointForReing) || !(lineString2 is LinearRing))
					{
						return false;
					}
					list.Add(lineString2 as LinearRing);
				}
			}
			return this.TryCreatPolygon(lineString as LinearRing, out creatResult, list);
		}

		internal bool TryMakePolygon(HYPolygon inputHYPolygon, out Polygon creatResult, bool ifAddEndPointForReing = false)
		{
			creatResult = null;
			return inputHYPolygon != null && this.TryMakePolygon(inputHYPolygon.ShellPoints, out creatResult, ifAddEndPointForReing, inputHYPolygon.LstHolPoints);
		}

		private Coordinate CreatOneCoordinate(double x, double y)
		{
			return new Coordinate(x, y);
		}

		private bool TryCreatLine(List<Coordinate> lstInputCoordinate, out LineString creatResult)
		{
			creatResult = null;
			if (lstInputCoordinate == null || lstInputCoordinate.Count < 2)
			{
				return false;
			}
			if (lstInputCoordinate[0].Equals2D(lstInputCoordinate[lstInputCoordinate.Count - 1]))
			{
				LinearRing linearRing = null;
				this.TryCreatLinearRing(lstInputCoordinate, out linearRing);
				creatResult = linearRing;
				return null != creatResult;
			}
			return this.TryCreatLineString(lstInputCoordinate, out creatResult);
		}

		private bool TryCreatLineString(List<Coordinate> lstInputCoordinate, out LineString creatResult)
		{
			creatResult = null;
			bool result;
			try
			{
				creatResult = (this.m_useGeometryFactory.CreateLineString(lstInputCoordinate.ToArray()) as LineString);
				result = (null != creatResult);
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private bool TryCreatLinearRing(List<Coordinate> lstInputCoordinate, out LinearRing creatResult)
		{
			creatResult = null;
			bool result;
			try
			{
				creatResult = (this.m_useGeometryFactory.CreateLinearRing(lstInputCoordinate.ToArray()) as LinearRing);
				result = (null != creatResult);
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private bool TryCreatPolygon(LinearRing shell, out Polygon creatResult, List<LinearRing> holes = null)
		{
			creatResult = null;
			bool result;
			try
			{
				if (holes == null)
				{
					creatResult = (this.m_useGeometryFactory.CreatePolygon(shell) as Polygon);
				}
				else
				{
					creatResult = (this.m_useGeometryFactory.CreatePolygon(shell, holes.ToArray()) as Polygon);
				}
				result = (null != creatResult);
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private GeometryFactory m_useGeometryFactory = new GeometryFactory(new PrecisionModel(PrecisionModels.Floating));

		private static NtsGeometryGeter m_signalTag;
	}
}
